package com.triones.api.service.impl;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.php.BankCardApplyStatus;
import com.ruoyi.common.enums.php.OpenCardStatus;
import com.ruoyi.common.enums.php.OpenCardTransactionType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.SnowflakeIdWorker;
import com.triones.api.entity.*;
import com.triones.api.entity.bo.UpdateCardRequestBodyBO;
import com.triones.api.entity.param.CardDetailParams;
import com.triones.api.entity.vo.CryptoInCommonUseAddressVO;
import com.triones.api.entity.vo.CustomEcWalletBillVO;
import com.triones.api.entity.vo.EcWalletBillVO;
import com.triones.api.entity.vo.FaitWalletVO;
import com.triones.api.mapper.*;
import com.triones.api.service.FaitWalletService;
import com.triones.api.service.third.PhotonPayService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;

/**
 * 法定货币钱包 -业务实现
 */
@Service
@RequiredArgsConstructor
public class FaitWalletServiceImpl implements FaitWalletService {

    private final FaitWalletMapper faitWalletMapper;

    private final EcWalletBillMapper ecWalletBillMapper;

    private final BankCardMapper bankCardMapper;

    private final BankCardUpdateRecordMapper bankCardUpdateRecordMapper;

    private final PhotonPayService photonPayService;

    @Override
    public List<FaitWalletVO> apiWalletList() {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        LambdaQueryWrapper<FaitWalletDO> lqw = Wrappers.lambdaQuery();
        lqw.eq(FaitWalletDO::getUid, loginUser.getUserId())
            .eq(FaitWalletDO::getStatus, "0");
        lqw.orderByDesc(FaitWalletDO::getCreateTime);
        return faitWalletMapper.selectVoList(lqw);
    }

    @Override
    public FaitWalletVO walletDetail(String ccy) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        return faitWalletMapper.selectVoOne(new LambdaQueryWrapper<FaitWalletDO>()
            .eq(FaitWalletDO::getUid, loginUser.getUserId())
            .eq(FaitWalletDO::getCurrency, ccy));
    }

    @Override
    public TableDataInfo<CustomEcWalletBillVO> apiTradePageList(String ccy, PageQuery pageQuery, String txnType) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("当前用户退出登录!");
        }
        QueryWrapper<Object> wrapper = Wrappers.query();
        wrapper.eq("tewb.uid", loginUser.getUserId())
            .eq("tewb.currency", ccy);
        if (OpenCardTransactionType.AUTH.getCode().equals(txnType)) {
            wrapper.in("tewb.txn_type",
                OpenCardTransactionType.AUTH.getCode(),
                OpenCardTransactionType.VOID.getCode(),
                OpenCardTransactionType.REFUND.getCode(),
                OpenCardTransactionType.RECHARGE_RETURN.getCode(),
                OpenCardTransactionType.SERVICE_FEE.getCode(),
                OpenCardTransactionType.REFUND_REVERSAL.getCode(),
                OpenCardTransactionType.OPEN_CARD_FEE.getCode(),
                OpenCardTransactionType.CARD_MGR_FEE.getCode()
            );
        }
        if (OpenCardTransactionType.EXCHANGE.getCode().equals(txnType)) {
            wrapper.eq("tewb.txn_type", OpenCardTransactionType.EXCHANGE.getCode());
        }
        if (OpenCardTransactionType.ATM_WITHDRAWALS.getCode().equals(txnType)) {
            wrapper.eq("tewb.txn_type", OpenCardTransactionType.ATM_WITHDRAWALS.getCode());
        }
        wrapper.orderByDesc("tewb.transacted_at");
        Page<CustomEcWalletBillVO> result = ecWalletBillMapper.apiTradePageList(pageQuery.build(), wrapper);
        return TableDataInfo.build(result);
    }

    @Override
    public EcWalletBillVO apiTradeDetail(Long id) {
        return ecWalletBillMapper.selectVoById(id);
    }

    @Override
    public void fiatWalletCardUpdate(Long uid, String ccy, BigDecimal amount, String transactionType,String excludeCardId) {
        /**
         * 钱包更新
         */
        FaitWalletDO faitWalletDO = faitWalletMapper.selectOne(new LambdaQueryWrapper<FaitWalletDO>()
            .eq(FaitWalletDO::getUid, uid)
            .eq(FaitWalletDO::getCurrency, ccy));
        if (faitWalletDO != null) {
            if ("increase".equals(transactionType)) {
                faitWalletDO.setAmount(faitWalletDO.getAmount().add(amount));
            } else {
                BigDecimal subtract = faitWalletDO.getAmount().subtract(amount);
                faitWalletDO.setAmount(subtract);
                if (subtract.compareTo(BigDecimal.ZERO) == -1) {
                    faitWalletDO.setAmount(BigDecimal.ZERO);
                }
            }
            faitWalletDO.setUpdateTime(System.currentTimeMillis());
            faitWalletMapper.updateById(faitWalletDO);

            LambdaQueryWrapper<BankCardDO> lqw = new LambdaQueryWrapper<BankCardDO>();
            lqw.eq(BankCardDO::getUid, uid).ne(BankCardDO::getStatus, OpenCardStatus.CANCELLED.getCode());
            List<BankCardDO> cardDOS = bankCardMapper.selectList(lqw);
            if (cardDOS.size() > 0) {
                for (BankCardDO cardDO : cardDOS) {
                    if (excludeCardId != null && excludeCardId.equals(cardDO.getCardId())) {
                        /**
                         * 查询卡详情
                         */
                        CardDetailParams cardDetailParams = new CardDetailParams();
                        cardDetailParams.setCardId(cardDO.getCardId());
                        Map cardDetail = photonPayService.getCardDetail(cardDetailParams);
                        if (cardDetail != null) {
                            cardDO.setTransactionLimit(Convert.toStr(cardDetail.get("availableTransactionLimit")));
                            cardDO.setUpdatedAt(Convert.toStr(System.currentTimeMillis()));
                            bankCardMapper.updateById(cardDO);
                        }
                    } else {
                        String requestId = Convert.toStr(SnowflakeIdWorker.generateUniqueId());
                        UpdateCardRequestBodyBO updateCardRequestBodyBO = new UpdateCardRequestBodyBO();
                        updateCardRequestBodyBO.setRequestId(requestId);
                        updateCardRequestBodyBO.setCardId(cardDO.getCardId());
                        updateCardRequestBodyBO.setTransactionLimit(Convert.toStr(amount));
                        updateCardRequestBodyBO.setTransactionLimitType("limited");
                        updateCardRequestBodyBO.setTransactionLimitChangeType(transactionType);
                        Map map = photonPayService.updateCard(updateCardRequestBodyBO);
                        if (map != null) {
                            /**
                             * 卡更新记录
                             */
                            BankCardUpdateRecordDO bankCardUpdateRecordDO = new BankCardUpdateRecordDO();
                            bankCardUpdateRecordDO.setCardId(cardDO.getCardId());
                            bankCardUpdateRecordDO.setRequestId(requestId);
                            bankCardUpdateRecordDO.setUid(uid);
                            bankCardUpdateRecordDO.setTransactionLimit(Convert.toStr(amount));
                            bankCardUpdateRecordDO.setTotalTransactionLimit(Convert.toStr(map.get("totalTransactionLimit")));
                            bankCardUpdateRecordDO.setAvailableTransactionLimit(Convert.toStr(map.get("availableTransactionLimit")));
                            bankCardUpdateRecordDO.setCreatedAt(System.currentTimeMillis());
                            bankCardUpdateRecordDO.setTransactionLimitChangeType(transactionType);
                            bankCardUpdateRecordMapper.insert(bankCardUpdateRecordDO);

                            cardDO.setTransactionLimit(Convert.toStr(map.get("availableTransactionLimit")));
                            cardDO.setUpdatedAt(Convert.toStr(System.currentTimeMillis()));
                            bankCardMapper.updateById(cardDO);
                        }
                    }
                }
            }
        }
    }
}
